import { eachDayOfInterval, endOfMonth, startOfMonth, getDay, subDays, addDays, getDate, getMonth, getYear, isWithinInterval, subMonths, addMonths, eachMonthOfInterval, startOfWeek, endOfWeek, subWeeks, addWeeks, eachWeekOfInterval } from 'date-fns';
interface Option {
  current?: Date,
  direction?: string,
  min?: string,
  max?: string,
  startOnWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6
}
interface Item {
  date?: Date,
  min?: string,
  max?: string,
  startOnWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
  direction?:string
}
export default {
  getMonthDays (opt:Option) {
    const {current, direction, min, max, startOnWeek} = opt
    const isVertical = direction === 'vertical'
    const start = isVertical ? new Date(min) : subMonths(startOfMonth(current), 1)
    const end = isVertical ? new Date(max) : addMonths(endOfMonth(current), 1)
    const months = eachMonthOfInterval({start, end})
    let array = []
    months.forEach((date, i) => {
      array[i] = this.generateMonth({min, max, date, direction, startOnWeek})
    })
    return array
  },
  generateMonth (item:Item): Date[] {
    const {min, max, date, startOnWeek, direction} = item
    const mind = new Date(min)
    const maxd = new Date(max)
    const start = date
    const end = endOfMonth(date)
    let array = eachDayOfInterval({start, end})
    let data = []
    array.forEach((item, i) => {
      const isIn = isWithinInterval(item, {
        start: mind,
        end: maxd
      })
      data[i] = {
        value: item,
        disabled: !isIn,
        isout: !isIn,
        ...this.getDateInfo(item)
      }
    })
    const startWeek = getDay(start)
    const pc = startWeek - startOnWeek
    let prev = []
    for (let i = 0; i < pc; i ++) {
      const item = subDays(start, pc - i)
      prev[i] = {
        value: item,
        disabled: true,
        ...this.getDateInfo(item)
      }
    }
    data = [...prev, ...data]
    let nlength = direction === 'horizontal' ? 42 : Math.ceil(array.length / 7) * 7
    nlength = nlength - data.length
    let next = []
    for (let i = 0; i < nlength; i ++) {
      const item = addDays(end, i + 1)
      next[i] = {
        value: item,
        disabled: true,
        ...this.getDateInfo(item)
      }
    }
    data = [...data, ...next]
    return data
  },
  generateWeek (item:Item) {
    const {min, max, date, startOnWeek} = item
    const mind = new Date(min)
    const maxd = new Date(max)
    const start = startOfWeek(date, {
      weekStartsOn: startOnWeek
    })
    const end = endOfWeek(date, {
      weekStartsOn: startOnWeek
    })
    const array = eachDayOfInterval({start, end})
    let data = []
    array.forEach((item, i) => {
      const isIn = isWithinInterval(item, {
        start: mind,
        end: maxd
      })
      data[i] = {
        value: item,
        disabled: !isIn,
        ...this.getDateInfo(item)
      }
    })
    return data
  },
  getWeekDays (opt: Option) {
    const {current, direction, min, max, startOnWeek} = opt
    const isVertical = direction === 'vertical'
    const start = isVertical ? new Date(min) : subWeeks(current, 1)
    const end = isVertical ? new Date(max) : addWeeks(current, 1)
    const weeks = eachWeekOfInterval({start, end}, {
      weekStartsOn: startOnWeek
    })
    let array = []
    weeks.forEach((date, i) => {
      array[i] = this.generateWeek({
        date, current, direction, min, max, startOnWeek
      })
    })
    return array
  },
  getDateInfo (item) {
    return {
      day: getDate(item),
      month: getMonth(item) + 1,
      year: getYear(item),
      week: getDay(item)
    }
  }
}